package jar

/**
  *
  * Author: Steve Kore
  * E-mail: huangke7296@foxmail.com
  * GitHub: https://github.com/KoreHuang
  * TelPho: 15829262572
  * TimeCr: 2018/1/17 下午3:00
  *
  */


object FunctinalTest {


  def main(args: Array[String]): Unit = {


    {
      val strCovert = (s: String) => s.toLowerCase //函数字面值(Function Literal)

      println(strCovert("HELLO,WORLD"))

      var strCovert2 = new Function1[String, String] {
        override def apply(s: String): String = s.toLowerCase
      }

      println(strCovert2("HELLO,WORLD"))

      var strCovert3 = new (String => String) {
        override def apply(v1: String): String = {
          v1.toLowerCase
        }
      } //匿名函数对象

    } //匿名函数的编写方法本质上是new Function1[T,N]{}的语法糖


    {
      // 在函数式编程中，函数做为一等公民，函数值可以被自由地传递和存储

      def mapValue[A, B](f: B => A)(a: B): A = f(a) //柯里化方法

      println(mapValue((s: String) => s.toLowerCase)("HELLO<WORLD"))

      val xmap = mapValue _ //η扩展

      def mapValueFunctionNameTheOne: (String => String) => String => String = (f) => f //柯里化函数

      println(mapValueFunctionNameTheOne((s: String) => s.toLowerCase)("HELLO<WORLD"))

      var mapValueFunctionNameTheTwo: (String => String) => String => String = (f) => f //柯里化函数常量

      val mapValueFunctionNameTheThree: (String => String) => String => String = (f) => f //柯里化函数常量

      println("************")

      println(mapValueFunctionNameTheOne eq mapValueFunctionNameTheOne)

      println(mapValueFunctionNameTheTwo eq mapValueFunctionNameTheTwo)

      println(mapValueFunctionNameTheThree eq mapValueFunctionNameTheThree)

      println("************")


    } //  使用 val 定义函数 和 def 定义函数的区别 以及函数与方法的区别


    {

      type StringMatcher = String => (String => Boolean)

      def starts: StringMatcher = (prefix: String) => (s) => s startsWith prefix // 在某些场景中应用 _ 会自动转为 (x$1)=>x$1

      def ends: StringMatcher = (suffix: String) => _ endsWith suffix

      def contains: StringMatcher = (substr: String) => _ contains substr


      def ignoringCase(matcher: StringMatcher): StringMatcher = (substr: String) => ((str: String) => matcher(substr.toLowerCase)(str.toLowerCase))

      println(ignoringCase(starts)("hello")("Hello,world"))

    } // 高阶函数

    println("************")


    {

      def times: Int => Int => Boolean = m => n => n % m == 0

      var twice = times(2)

      var trible = times(3)

      println(twice(4))
      println(twice(5))

      println(trible(6))
      println(trible(7))

      def times2(m: Int)(n: Int): Boolean = n % m == 0

      // var twice2=times2(2)     error    times2(2)返回值得类型为(Int)Boolean，不是一个函数 不能赋值给变量
      var twice2 = times2(2) _ // 需要使用 _ η扩展称为一个部分应用函数

      println(twice2(4))

      // 如果上下文标明了函数的类型，编译器会自动实施η扩展


      def atom(matcher: Int => Boolean, action: Int => String): Int => String = m => if (matcher(m)) action(m) else ""

      def to(s: String): Int => String = _ => s

      val r_1 = atom(times2(3), to("Fizz"))

      println(r_1(6))


    } // 部分应用函数、η扩展、自动扩展

    println("************")

    {
      val positive:PartialFunction[Int,Int]={case x if x>0=>{x}}

      println(positive(1))    // 等同于   val positive = new PartialFunction[Int, Int] { def isDefinedAt(x: A): Boolean = x > 0; def apply(x: Int): Int = x}

      // println(positive(-1))   scala.MatchError: -1

      val positiveOption = positive.lift  // 通过lift，可以将positive提升为Int => Option[Int]的一元函数。

      val positive2 = Function.unlift(positiveOption) // 如果对一元函数positiveOption调用Function.unlift，将使得该一元函数降级为一个偏函数

    }//偏函数剖析升级为一元函数和一元函数降级为偏函数
    println("************")


    {
      def lowerdefmethod(s: String):String = s toLowerCase  //方法形式存在的函数

      def lowerdeffunction: String => String = _ toLowerCase
      def lowernameed: Function1[String, String] = _ toLowerCase()  //使用def 定义的方法 返回Function1类型的函数

      val lowerval:String=>String = _ toLowerCase
      val lowernominate:Function1[String, String] = _ toLowerCase
      val loweranonymous=(s:String)=>s toLowerCase

    } //函数形态
    println("************")

    {
      def lower(s:String):String = s toLowerCase

      def map(s:String)(f:String=>String):String = f(s)

      def mapValue[A, B](f: B => A)(a: B): A = f(a) // 柯里化方法

      def maocommonev[A,B]:A=>(A=>B)=>B = x=>f=>f(x)  // 日了他爸爸的转化

      println( maocommonev("SCALA TEST")(lower) )

      // val lo=lower 错误 lower 不是一个函数值类型的变量 不可以用来赋值

      val lo = lower _ //使用 η 扩展 返回Function1类型的变量值 可以赋值给lo变量

      println( map("SCALA TEST")(lower) )  // 方法入参时 编译器自动完成 η 扩展

      println( map("SCALA TEST")(lower _) ) // 与上面的调用方式等价

      println( map("SCALA TEST")(lo) )

    }

    println("************")



  }


}
